package com.cskaoyan.wordmemorize.Aspect;


import com.alibaba.fastjson.JSON;
import com.cskaoyan.wordmemorize.annotation.OperateLog;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.dao.entity.OperateLogDO;
import com.cskaoyan.wordmemorize.dao.mapper.OperateLogMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;


@Component
@Aspect
public class MyAspect {

    @Pointcut("@annotation(com.cskaoyan.wordmemorize.annotation.OperateLog)")
    public void operateLog() {
    }

    @Autowired
    OperateLogMapper operateLogMapper;

    @Around("operateLog()")
    @Transactional
    public Object aroundOperateLog(ProceedingJoinPoint joinPoint) {

        long employeeid = StpKit.ADMIN.getLoginIdAsLong();
        // 获取方法传入的参数
        Object[] args = joinPoint.getArgs();
        // 获取方法的注解的参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        OperateLog operateLog = signature.getMethod().getAnnotation(OperateLog.class);
        String dateType = operateLog.dateType();    // 描述操作的数据，比如: 书籍，单词，角色，权限,等级,等级特权
        int operateType = operateLog.operateType();  // 描述操作的类型: 1. 新增 2. 修改 3. 单个删除 4. 批量删除 5. 修改状态 6. excel导入
        int status = 0; // 操作状态：0. 失败 1. 成功

        Object result = null;
        // 创建日志对象
        OperateLogDO operateLogDO = new OperateLogDO();
        operateLogDO.setEmployeeId(employeeid);
        operateLogDO.setDataType(dateType);
        operateLogDO.setOperateType(operateType);

        try {
            // 执行方法
            result = joinPoint.proceed(args);
            status = 1;
            operateLogDO.setStatus(status);
            addOperationLog(operateType, args, operateLogDO, result);
        } catch (Throwable e) {
            status = 0;
            operateLogDO.setStatus(status);
            addOperationLog(operateType, args, operateLogDO, result);
            throw new RuntimeException(e);
        }

        return result;

    }

    private void addOperationLog(int operateType, Object[] args, OperateLogDO operateLogDO, Object result) {
        // - 针对新增1和修改2数据，我们可以将`请求参数`转化为json字符串，放入admin_operate_log中的data字段
        // args转为json字符串
        if (operateType == 1 || operateType == 2 || operateType == 5) {
            String data = JSON.toJSONString(args);
            operateLogDO.setData(data);
        }

        //- 针对excel导入数据6，我们也可以将`返回值`转化为json字符串（ExcelAddOperateDTO），放入admin_perate_log的data字段
        else if (operateType == 6) {
            String data = JSON.toJSONString(result);
            operateLogDO.setData(data);

        //- 针对删除数据，因为无论是单个删除3，还是批量删除4，参数都只有id，所以我们把删除`方法返回值`转化为admin_operate_log的data字段
        }
        else if (operateType == 3 || operateType == 4) {
            String data = JSON.toJSONString(result);
            operateLogDO.setData(data);
        }

        // 插入日志
        operateLogMapper.insert(operateLogDO);
    }
}
